package com.gitee.wsl.jvm.okhttp.request

import com.gitee.wsl.jvm.okhttp.base.executeCancellableAsync
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okio.IOException


/**
 * Request
 */

fun Request.asyncCall(client: OkHttpClient, respFun:(Result<Response>)->Unit) = client.newCall(this).apply {
    enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            respFun(Result.failure(e))
        }

        override fun onResponse(call: Call, response: Response) {
            response.use {
                if (!response.isSuccessful)
                    respFun(Result.failure(IOException("Unexpected code $response")))
                else
                    respFun(Result.success(response))
            }
        }
    })
}


fun Request.flowCall(client: OkHttpClient) = flow {
    asyncCall(client){
        runBlocking {
            emit(it)
        }
    }
}

suspend fun Request.asyncWithCancelableCall(client: OkHttpClient)
        = client.newCall(this).executeCancellableAsync()

/**
 * Sets a single-part `Range` header with the given [start] offset.
 *
 * Specification: [RFC 9110, Section 14.2](https://www.rfc-editor.org/rfc/rfc9110.html#section-14.2)
 */
fun Request.Builder.setRangeHeader(start: Long): Request.Builder {
    require(start >= 0) { "The start position must not be less than zero." }
    return header("Range", "bytes=$start-")
}

/**
 * Sets a single-part `Range` header with the given [start] and [endInclusive] offset.
 *
 * Specification: [RFC 9110, Section 14.2](https://www.rfc-editor.org/rfc/rfc9110.html#section-14.2)
 */
fun Request.Builder.setRangeHeader(start: Long, endInclusive: Long): Request.Builder {
    require(start >= 0) { "The start position must not be less than zero." }
    require(endInclusive >= start) { "The end position must not be less than the start position." }
    return header("Range", "bytes=$start-$endInclusive")
}

/**
 * Sets a single-part `Range` header with the given [suffixLength].
 *
 * Specification: [RFC 9110, Section 14.2](https://www.rfc-editor.org/rfc/rfc9110.html#section-14.2)
 */
fun Request.Builder.setSuffixRangeHeader(suffixLength: Long): Request.Builder {
    require(suffixLength > 0) { "The suffix length must be greater than zero." }
    return header("Range", "bytes=-$suffixLength")
}